/*
 * 通过密钥文件得到其MD5值//同理可以使用其他类型的hash值
 * 将MD5值转换为一个长度为16的byte数组
 * 将byte数组的所有值都转换为正数相加得到和sum
 * 输入流一次读取sum个字节
 * 将sum个字节分为16组
 * 每组字节数对应为byte数组每个元素正数数量的字节
 * 对每组字节进行异或运算
 * 
 * 用来做异或运算的数是对0xf进行操作所得
 * i=sum%4，(0xf>>i)<<i，即可得到1111，1110，1100，1000
 * 再得到11110000 11110000，11100000 11100000，11000000 11000000，10000000 10000000
 * 对每组字节数进行异或操作后，上述四个数右移一位，即每8组所做的异或操作相同
 * 
 * 加密完成后提示是否删除原文件
 * 文件长度小于sum时，并未加密
 */

package mytool;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.swing.JOptionPane;

/**
 *
 * @author heantai
 */
class MyEncriptor {
public boolean encripted=false;
   void encript(File keyFile, File tobeEncripted, File saved) throws FileNotFoundException, IOException, NoSuchAlgorithmException {
   FileInputStream in = new FileInputStream(keyFile);
		byte[] buf = new byte[1024];
		MessageDigest md5 = MessageDigest.getInstance("md5");
		int numRead;
		while ((numRead = in.read(buf)) != -1) {
			md5.update(buf, 0, numRead);
		}
		in.close();
		byte[] bs = md5.digest();
		int sum = 0;
		int[] len = new int[16];
		for (int i = 0; i < bs.length; i++) {
			sum+=bs[i]&0xff;
			len[i]=bs[i]&0xff;
		}
		in = new FileInputStream(tobeEncripted);
		buf = new byte[sum];
		FileOutputStream out = new FileOutputStream(saved);
		byte[] bufout = new byte[sum];
		int num;
		
		int yushu=sum%4;
		int yiweihou=(0xf>>yushu)<<yushu;//1111，1110，1100，1000
		int yihoulai=yiweihou<<4|yiweihou<<12;//11110000 11110000，11100000 11100000，11000000 11000000，10000000 10000000
		
		while((num=in.read(buf))==sum){
			int leng=0;
			int length=len[0];
			int lenCount=0;
			int yudeshu=yihoulai;
			for (int j = 0; j < 16; j++) {
				for (int i = leng; i < length; i++) {
					bufout[i]=(byte) (buf[i]^yudeshu);
				}
				leng=length;
				if(lenCount<15){//防止l++enCount为16造成数组越界
					yudeshu>>=1;
					length+=len[++lenCount];
				}
			}
			out.write(bufout);
			out.flush();
		}
		out.write(buf,0,num);
		out.flush();
		out.close();
		in.close();
   encripted = true;
   JOptionPane.showMessageDialog(null, "加密／解密完成");
    }

}
